package org.swimv2.sessions;

import java.util.Collection;
import java.util.Date;
import java.util.Set;

import javax.ejb.Stateless;
import javax.naming.Context;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.ejb3.annotation.RemoteBinding;
import org.swimv2.entities.FriendshipRequest;
import org.swimv2.entities.User;
import org.swimv2.interfaces.FriendshipManagerRemote;
import org.swimv2.interfaces.SearchManagerRemote;
import org.swimv2.utils.ContextUtil;

/**
 * Session Bean implementation class FriendshipManager
 */
@Stateless
@RemoteBinding(jndiBinding="FriendshipManagerJNDI")
public class FriendshipManager implements FriendshipManagerRemote {
	
	@PersistenceContext(unitName="JPADB")
    private EntityManager manager;
	
	@Override
	public Collection<User> listFriends(User user) {
		
		String q = "SELECT u FROM User AS u1, IN(u1.friend1) u WHERE u1 = :user ";
		String r = "SELECT u2 FROM User AS u3, IN(u3.friend2) u2 WHERE u3 = :user3"; 
		
		Query que = manager.createQuery(q);
		que.setParameter("user", user);
		
		Query que1 = manager.createQuery(r);
		que1.setParameter("user3", user);
		
		Collection<User> r1 = (Collection<User>) que.getResultList();
		
		Collection<User> r2 = (Collection<User>) que1.getResultList();
		
		r1.addAll(r2);
		
		return r1;
		
	}

	@Override
	public void sendFriendshipReq(User sender, User receiver, Date date) {
		try {
			FriendshipRequest fr = new FriendshipRequest();
			
			fr.setSender(sender);
			fr.setReceiver(receiver);
			fr.setDate(date);
			
			manager.persist(fr);
		}
		catch (EntityExistsException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public FriendshipRequest getRequest(int id) {
		FriendshipRequest r;
		
		try {
			Query q = manager.createNamedQuery("FriendshipRequest.getById");
			q.setParameter("id", id);
			r = (FriendshipRequest) q.getSingleResult();
		}
		catch (Exception e) {
			return null;
		}
		return r;
	}

	@Override
	public Collection<User> listFriendshipReq(User user) { 
		
		String q = "SELECT DISTINCT r.sender FROM FriendshipRequest r " +
				"WHERE r.receiver = :receiver";	
		
		Query que = manager.createQuery(q);
		
		que.setParameter("receiver", user);
		
		Collection<User> res = que.getResultList();
		
		return res;
		
	}

	@Override
	public void addFriendship(User sender, User receiver) {
		try {
			
			sender = manager.merge(sender);
			receiver = manager.merge(receiver);
			
			if(sender.getId() < receiver.getId()) {
				sender.getFriend2().add(receiver);
				receiver.getFriend1().add(sender);
			}
			
			else {
				sender.getFriend1().add(receiver);
				receiver.getFriend2().add(sender);
			}
			
			manager.flush();
			
			String r = "DELETE FROM FriendshipRequest fr WHERE " +
					"fr.sender = :sender AND fr.receiver = :receiver";
			
			manager.flush();
			
			Query que3 = manager.createQuery(r);
			que3.setParameter("sender", sender);
			que3.setParameter("receiver", receiver);
			
			que3.executeUpdate();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		
	}

	@Override
	public void removeFriendship(User user1, User user2) {
		try {
			Context ctx = ContextUtil.getInitialContext();
			SearchManagerRemote mgr_s = (SearchManagerRemote) ctx.lookup("SearchManagerJNDI");
			User u1 = mgr_s.getUserById(user1.getId());
			User u2 = mgr_s.getUserById(user2.getId());
			
			if( user1.getId() < user2.getId() ) {
				Set<User> list = u1.getFriend1();
				list.remove(u2);
				u1.setFriend1(list);
				
				list = u2.getFriend2();
				list.remove(u1);
				u2.setFriend2(list);
			}
			
			else {
				Set<User> list = u1.getFriend2();
				list.remove(u2);
				u1.setFriend2(list);
				
				list = u2.getFriend1();
				list.remove(u1);
				u2.setFriend1(list);
			}
			
			manager.merge(user1);
			manager.merge(user2);
			
//			String q = "UPDATE User u1 SET u1.friend1 = :friend11 AND " +
//					"u1.friend2 = :friend21 WHERE u1.id = :user1";
//			
//			String p = "UPDATE User u2 SET u2.friend1 = :friend12 AND " +
//					"u2.friend2 = :friend22 WHERE u2.id = :user2";
//			
//			
//			manager.flush();
//			
//			Query que1 = manager.createQuery(q);
//			que1.setParameter("friend11", user1.getFriend1());
//			que1.setParameter("friend21", user1.getFriend2());
//			que1.setParameter("user1", user1);
//			
//			que1.executeUpdate();
//			
//			Query que2 = manager.createQuery(p);
//			que2.setParameter("friend12", user2.getFriend1());
//			que2.setParameter("friend22", user2.getFriend2());
//			que2.setParameter("user2", user2);
//			
//			que2.executeUpdate();
		
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	
	
	@Override
	public boolean isFriendOf(User us1, User us2) {
		us1 = manager.merge(us1);
		us2 = manager.merge(us2);
		
		if (listFriends(us1).contains(us2))
			return true;
		if (listFriends(us2).contains(us1))
			return true;
		else
			return false;
	}
	
	

	@Override
	public boolean removeFriendshipReq(User sender, User receiver) {
		String r = "DELETE FROM FriendshipRequest fr WHERE " +
				"fr.sender = :sender AND fr.receiver = :receiver";
		
		manager.flush();
		
		Query que3 = manager.createQuery(r);
		que3.setParameter("sender", sender);
		que3.setParameter("receiver", receiver);
		
		int k = que3.executeUpdate();
		
		return k > 0;
	
	}
}
